package com.elite.groovy.callback

import com.alibaba.fastjson.JSONObject
import com.elite.groovy.kh.KHUtil
import com.elite.groovy.util.EliteBean
import com.wisdge.dataservice.Result
import org.apache.commons.logging.Log
import org.apache.commons.logging.LogFactory
import org.springframework.jdbc.core.JdbcTemplate
import org.springframework.jdbc.support.rowset.SqlRowSet

import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse

/**
 *
 * @Title: 项目表数据同步接口
 *
 */

public class apiSyncDBData implements ServiceBackInvoke {
    private static final Log log = LogFactory.getLog(apiSyncDBData.class);

    public String doCallBack(EliteBean eliteBean, HttpServletRequest request, HttpServletResponse response) {

        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json;charset=UTF-8");
        long startTime = System.currentTimeMillis();

        String getMethod = request.getMethod();
        log.debug("apiSyncDBData getMethod:" + getMethod);
        String outData = "";
        if (getMethod != "GET") {
            outData = "HTTP请求调用类型错误，接口调用失败：" + getMethod;
            log.error(outData);
            return JSONObject.toJSONString(new Result(Result.ERROR, outData));
        }

        //获取所有参数名
        Enumeration ep = request.getParameterNames();
        while (ep.hasMoreElements()) {
            String parameterName = (String) ep.nextElement();
            log.debug(parameterName + ": " + request.getParameter(parameterName));
        }

        // 获取嵌入传递的参数
        String taskname = request.getParameter("taskname");
        if (KHUtil.isNull(taskname)) {
            outData = "apiSyncDBData HTTP请求调用错误，任务ID为空：" + taskname;
            log.error(outData);
            return JSONObject.toJSONString(new Result(Result.ERROR, outData));
        }

        // 获取数据源List<Map<String, Object>>
        JdbcTemplate def_jt = new JdbcTemplate(eliteBean.getDataSource());
        JdbcTemplate in_jt = new JdbcTemplate();
        JdbcTemplate out_jt = new JdbcTemplate();

        //获取批次是否已经发送(运行标识1&运行时间10分钟内)-暂时这个保护比较弱,主要防止人为
        String checkSQL = '''Select Rec_Guid
                              From Autosyncdatasconfig
                             Where Taskname = ?
                               And Status = 1
                               And Cur_Run_Flag = 1
                               And Last_Run_Time > Date_Add(Now(), Interval - 10 * 60 Second)''';
        List<Map<String, Object>> checkSQLList = def_jt.queryForList(checkSQL, taskname);
        if (checkSQLList.size() > 0) {
            outData = "apiSyncDBData HTTP请求调用错误，批次ID可能在执行中：" + checkSQLList.toString();
            log.error(outData);
            return JSONObject.toJSONString(new Result(Result.ERROR, outData));
        }

        long dbStartTime = System.currentTimeMillis();
        String Rec_Guid = "";

        try {
            // 获取任务配置基础数据
            String configSQL = '''Select Rec_Guid, In_Datasource, Select_Sql, Out_Datasource, Init_Sql, Update_Sql, Db_Batch_Num, Seq, Extra, Comments
                                      From Autosyncdatasconfig
                                     Where Status = 1
                                       And Taskname = ?
                                     Order By Seq''';
            List<Map<String, Object>> configSQLList = def_jt.queryForList(configSQL, taskname);

            for (int i = 0; i < configSQLList.size(); i++) {
                startTime = System.currentTimeMillis();
                Map configSQLMap = configSQLList.get(i);
                Rec_Guid = configSQLMap.get("Rec_Guid").toString();
                String In_Datasource = configSQLMap.get("In_Datasource").toString();
                String Select_Sql = configSQLMap.get("Select_Sql").toString();
                String Out_Datasource = configSQLMap.get("Out_Datasource").toString();
                String Init_Sql = configSQLMap.get("Init_Sql").toString();
                String Update_Sql = configSQLMap.get("Update_Sql").toString();
                int Db_Batch_Num = Integer.parseInt(configSQLMap.get("Db_Batch_Num").toString());
                String Extra = configSQLMap.get("Extra").toString();
                String Comments = configSQLMap.get("Comments").toString();
                log.debug("查询当前配置数据【" + Rec_Guid + "】：" + Rec_Guid + "【Comments】：" + Comments);

                // 更新当前任务执行中
                def_jt.update("Update Autosyncdatasconfig Set Cur_Run_Flag = 1, Last_Run_Time = Now() Where Rec_Guid = ?", Rec_Guid);

                // 查询当前配置SQL的数据
                in_jt = new JdbcTemplate(eliteBean.getDataSource(In_Datasource));
                out_jt = new JdbcTemplate(eliteBean.getDataSource(Out_Datasource));

                SqlRowSet result = in_jt.queryForRowSet(Select_Sql);
                int ColumnCount = result.getMetaData().getColumnCount();
                log.debug("查询当前配置SQL的数据列数:" + ColumnCount);

                // 判断是否有初始化SQL,如果有初始化SQL则执行
                if (!KHUtil.isNull(Init_Sql)) {
                    int init_num = out_jt.update(Init_Sql);
                    log.debug("存在初始化SQL,初始化SQL执行影响数量:" + init_num);

                }

                int totolNum = 0;
                int loopNum = 0;
                List<Object[]> paramListCus = new ArrayList<>();
                while (result.next()) {

                    String[] cusArr = new String[ColumnCount];
                    for (int j = 0; j < ColumnCount; j++) {
                        cusArr[j] = result.getString(j + 1);
                    }

                    paramListCus.add(cusArr);
                    loopNum++;
                    totolNum++;

                    // 如果当前批次已经到 Db_Batch_Num 提交一次DB
                    if (loopNum >= Db_Batch_Num) {
                        dbStartTime = System.currentTimeMillis();
                        out_jt.batchUpdate(Update_Sql, paramListCus);
                        log.debug("当前任务数据【" + Comments + "】：" + Rec_Guid + " #当前批次已经到" + loopNum + "提交一次DB End 耗时(毫秒):" + (System.currentTimeMillis() - dbStartTime).toString() + " 当前已同步:" + totolNum);

                        paramListCus.clear();

                        loopNum = 0;
                    }

                }

                // 最后批次未达到100提交一次DB
                if (loopNum > 0) {
                    dbStartTime = System.currentTimeMillis();
                    out_jt.batchUpdate(Update_Sql, paramListCus);
                    paramListCus.clear();

                    log.debug("当前任务数据【" + Comments + "】：" + Rec_Guid + " #最后批次未达到Db_Batch_Num提交一次DB:" + loopNum + "提交一次DB End 耗时(毫秒):" + (System.currentTimeMillis() - dbStartTime).toString() + " 当前已同步:" + totolNum);
                }

                outData = "查询当前配置数据【" + Comments + "】：" + Rec_Guid + " 总同步数量:" + totolNum + " 总耗时:" + (System.currentTimeMillis() - startTime).toString();

                // 更新当前任务执行结束
                def_jt.update("Update Autosyncdatasconfig Set Cur_Run_Flag = 2, Last_Run_Time = Now(), Extra = ? Where Rec_Guid = ?", outData, Rec_Guid);

            }

        } catch (Exception e) {
            outData = "apiSyncDBData HTTP请求调用错误，接口处理异常：" + e.getMessage();
            // 更新当前任务执行异常
            def_jt.update("Update Autosyncdatasconfig Set Cur_Run_Flag = -1, Last_Run_Time = Now(), Extra = ? Where Rec_Guid = ?", outData, Rec_Guid);
            log.error(outData, e);
            return JSONObject.toJSONString(new Result(Result.ERROR, outData));

        }

        return JSONObject.toJSONString(new Result(Result.SUCCESS, "数据同步完成"));
    }

}